package com.yunkeji.api.pay.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.baomidou.lock.exception.LockFailureException;
import com.ijpay.alipay.AliPayApi;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApiConfigKit;
import com.yunkeji.api.pay.bo.AliPayOrderCallBackBo;
import com.yunkeji.api.pay.bo.RechargeSuccessBo;
import com.yunkeji.api.pay.service.PayService;
import com.yunkeji.common.core.controller.BaseController;
import com.yunkeji.common.enums.app.PayStatusEnum;
import com.yunkeji.common.exception.AppServiceException;
import com.yunkeji.config.properties.PayProperties;
import com.yunkeji.dao.domain.PayDetail;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * 回调
 *
 * @author 老张
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/v1/callback")
@Slf4j
public class PayCallBackController extends BaseController {

    private final PayProperties payProperties;
    private final PayService payService;

    /**
     * 支付宝支付回调
     *
     * @author 老张
     * @param request
     * @return
     */
    @PostMapping(value = "/ali/notify_url")
    @ResponseBody
    public String notifyUrl(HttpServletRequest request) {
        try {
            // 获取支付宝POST过来反馈信息
            Map<String, String> params = AliPayApi.toMap(request);
            log.info("ali_notify_url=>" + JSONUtil.toJsonPrettyStr(params));

            //订单未支付成功直接返回
            if (!params.get("trade_status").equals("TRADE_SUCCESS"))
            {
                return "failure";
            }

            PayDetail payDetail = payService.findByOutTradeNo(params.get("out_trade_no"));
            if (payDetail == null) {
                throw AppServiceException.paramException("订单未找到");
            }
            if (payDetail.getStatus() != PayStatusEnum.未支付.getCode()) {
                throw AppServiceException.paramException("订单状态异常");
            }
            //通过订单的不同平台选择不同的公钥
            String publicKey;
//            if(payDetail.getBranch().toString().startsWith("3")){
//                publicKey = payProperties.getAli().getAliPayPublicKeyTwo();
//            } else {
                publicKey = payProperties.getAli().getAliPayPublicKey();
//            }
            boolean verifyResult =
                    AlipaySignature.rsaCheckV1(
                            params, publicKey, "UTF-8", "RSA2");
            if (verifyResult) {
                // 分布式锁,防止重复调用
                AliPayOrderCallBackBo aliPayOrderCallBackBo =
                        JSONUtil.toBean(JSONUtil.toJsonStr(params), AliPayOrderCallBackBo.class);
                try {

                    RechargeSuccessBo rechargeSuccessBo =
                            BeanUtil.toBean(aliPayOrderCallBackBo, RechargeSuccessBo.class);
                    payService.rechargeSuccess(rechargeSuccessBo);
                } catch (LockFailureException e) {
                    log.error("资源被占用:[]", e.getMessage());
                    return "failure";
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("发生其他异常:[]", e.getMessage());
                    return "failure";
                }
                return "success";
            } else {
                System.out.println("notify_url 验证失败");
                log.error("notify_url 验证失败,{}", params);
                return "failure";
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return "failure";
        }
    }

    /**
     * 微信支付回调
     *
     * @author 老张
     * @param request
     * @return
     */
    @PostMapping(value = "/wx/notify_url")
    public String payNotify(HttpServletRequest request) {
        // String xmlMsg = HttpKit.readData(request);
        JSONObject originBody = (JSONObject) request.getAttribute("originBody");
        Map<String, String> params = new HashMap<>();
        JSONObject xml1 = originBody.getJSONObject("xml");
        xml1.keySet().forEach(item -> params.put(item, xml1.getStr(item)));
        log.info("wx_notify_url=>" + JSONUtil.toJsonPrettyStr(params));
        String returnCode = params.get("return_code");
        String resultCode = params.get("return_code");

        //订单未支付成功直接返回
        if ((!WxPayKit.codeIsOk(returnCode)) || (!WxPayKit.codeIsOk(resultCode))) {
            return "failure";
        }

        // 注意重复通知的情况，同一订单号可能收到多次通知，请注意一定先判断订单状态
        // 注意此处签名方式需与统一下单的签名类型一致
        PayDetail payDetail = payService.findByOutTradeNo(params.get("out_trade_no"));
        if (payDetail == null) {
            throw AppServiceException.paramException("订单未找到");
        }
        if (payDetail.getStatus() != PayStatusEnum.未支付.getCode()) {
            throw AppServiceException.paramException("订单状态异常");
        }
        PayProperties.Wx wx = payProperties.getWx();
        String publicKey;
//        if(payDetail.getBranch().toString().startsWith("3")){
//            publicKey = wx.getApiKey();
//        } else {
            publicKey = wx.getPartnerKey();
//        }
        if (WxPayKit.verifyNotify(
                params,
                publicKey,
                SignType.HMACSHA256)) {

            // 分布式锁,防止重复调用
            try {
                RechargeSuccessBo build =
                        RechargeSuccessBo.builder()
                                .outTradeNo(params.get("out_trade_no"))
                                .tradeNo(params.get("transaction_id"))
                                .build();
                payService.rechargeSuccess(build);
            } catch (LockFailureException e) {
                log.error("资源被占用:[]", e.getMessage());
                return "failure";
            } catch (Exception e) {
                e.printStackTrace();
                log.error("发生其他异常:[]", e.getMessage());
                return "failure";
            }

            // 发送通知等
            Map<String, String> xml = new HashMap<String, String>(2);
            xml.put("return_code", "SUCCESS");
            xml.put("return_msg", "OK");
            return WxPayKit.toXml(xml);
        }

        return null;
    }
}
